from __future__ import with_statement

import os
import stat
import time
import glob
import shutil

# Can be changed at runtime
default_version_control_file_patterns = ['.svn']

def version_control_ignore(file_patterns=None):
    if file_patterns is None:
        file_patterns = default_version_control_file_patterns
    return shutil.ignore_patterns(*file_patterns)

def copy_tree(source_dir, destination_dir, vc_ignore = version_control_ignore()):
    if not os.path.isdir(destination_dir):
        if os.path.isfile(destination_dir):
            raise Exception('Error: "' + destination_dir + '" is an existing file not a directory!')
        os.makedirs(destination_dir)
    source_files = glob.glob(os.path.join(source_dir, '*'))
    for file in source_files:
        ignore_list = vc_ignore(source_dir, file)
        if file not in ignore_list:            
            if os.path.isfile(file):
                shutil.copy2(file, destination_dir)
            else:            
                copy_tree(file, os.path.join(destination_dir, os.path.basename(file), ''), vc_ignore=vc_ignore)

def forced_rmtree(path):
    def forced_remove_callback(function, path, excinfo):
        if function == os.remove:        
            os.chmod(path, stat.S_IREAD | stat.S_IWRITE)
            os.remove(path)
            return 0           
        elif function == os.rmdir:
            for i in range(10):
                try:        
                    os.chmod(path, stat.S_IREAD | stat.S_IWRITE)
                    time.sleep(0.01)
                    os.rmdir(path)
                    return i
                except:
                    time.sleep(0.1)
        raise

    if os.path.exists(path):
        shutil.rmtree(path, onerror=forced_remove_callback)

def replace_in_file(path, replacement_dict):
    with open(path, 'r+') as file:            
        content = file.read()
        for old, new in replacement_dict.iteritems():
            content = content.replace(old, new)
        file.seek(0)
        file.truncate()
        file.write(content)

    